import "reflect-metadata"; //反射-元数据

/** 延迟执行装饰器；
 * 方法装饰器；
 * @param times 延迟时长，ms
 * @returns
 */
export const sleepDecorator =
  (times: number): MethodDecorator =>
  (...args: any[]) => {
    const [, , descriptor] = args;
    const method = descriptor.value;
    descriptor.value = () => {
      setInterval(() => {
        method();
      }, times);
    };
  };

/** 错误装饰器
 *
 * @param target
 * @param propertyKey
 * @param descriptor
 */
export const errorDecorator: MethodDecorator = (
  target: Object,
  propertyKey: string | symbol,
  descriptor: PropertyDescriptor
) => {
  const method = descriptor.value;
  descriptor.value = () => {
    try {
      method();
    } catch (error: any) {
      console.log(`%c${error.message}`, "color:red;font-size:16px");
    }
  };
};

/** 属性装饰器，属性内容全部小写；
 *
 * @param target
 * @param propertyKey
 */
export const lowerDecorator: PropertyDecorator = (
  target: Object,
  propertyKey: string | symbol
) => {
  let value: string;
  Object.defineProperty(target, propertyKey, {
    get: () => {
      return value.toLowerCase();
    },
    set: (v) => {
      value = v;
    },
  });
};

// export const requiredDecorator: ParameterDecorator = (
//   target: Object,
//   propertyKey: string | symbol | undefined,
//   parameterIndex: number
// ) => {
//   let requiredParams: number[] = [];
//   requiredParams.push(parameterIndex);
//   Reflect.defineMetadata(
//     "required",
//     requiredParams,
//     target,
//     propertyKey as string | symbol
//   );
// };

/** 参数验证装饰器
 * 方法装饰器
 * @param target
 * @param propertyKey
 * @param descriptor
 */
// export const validateDecorator: MethodDecorator = (
//   target: Object,
//   propertyKey: string | symbol,
//   descriptor: PropertyDescriptor
// ) => {
//   const method = descriptor.value;
//   descriptor.value = function () {
//     const requiredParams: number[] =
//       Reflect.getMetadata("required", target, propertyKey) || [];
//     requiredParams.forEach((index) => {
//       if (index > arguments.length || arguments[index] == undefined) {
//         throw new Error("请传必要的参数！！");
//       }
//     });
//     return method.apply(this, arguments);
//   };
// };

/** 属性装饰器；
 * 验证属性值小于length报错装饰器
 * @param length 字符串长度
 * @returns
 */
export function MinLength(length: number) {
  return (target: any, propertyName: string) => {
    let value: string;
    const descriptor: PropertyDescriptor = {
      get() {
        return value;
      },
      set(newValue: string) {
        // 如果新值的长度小于length，抛出错误
        if (newValue.length < length) {
          throw new Error(propertyName + "长度不能小于" + length);
        }
        value = newValue;
      },
    };
    Object.defineProperty(target, propertyName, descriptor);
  };
}

type WatchedParameter = {
  methodName: string;
  parameterIndex: number;
};
const watchedParameters: WatchedParameter[] = [];

/** 参数装饰器；
 * 可观察的参数
 * @param target
 * @param methodName
 * @param parameterIndex
 */
export function Watch(target: any, methodName: string, parameterIndex: number) {
  watchedParameters.push({
    methodName,
    parameterIndex,
  });
}
